using System;
using System.Collections;
using System.Collections.Generic;
using Cinemachine;
using GameFramework.Battle.Core;
using Gameplay.PVE.Entity;
using Gameplay.PVE.TurnBase;
using Gameplay.PVE.Utils;
using Neonagee.LocalPreferences;
using TMPro;
using UnityEditor;
using UnityEngine;
using UnityEngine.Playables;
using XLua;
using Yoozoo.Framework.Managers;
using Yoozoo.Gta.Common;
using Yoozoo.HRP.Runtime;
using Yoozoo.Managers;
using Yoozoo.UI.YGUI;

namespace Gameplay.PVE
{
    public class PveScene
    {
        public static bool isInited;
        public static GameObject pveRoot;
        public static Transform pveRootTrans;
        public static bool IsTest;
        public static bool IsToRPG = false; //是否进场直接开始rpg
        public static bool IsToTurnBase;
        public static bool IsEditor = false;
        public static int heroCount = 6;

        public static bool isShowPveTestOnGUI = false;
        public static bool IsPassiveAllUnlock = false;
        public static int LevelId;
        public static bool isPause;

        public static bool RpgStart()
        {
            return PveManager.Instance.rpgStart;
        }

        public static void EnterScene()
        {
            if (IsToTurnBase)
            {
                //TurnBaseManager.Instance.Initialize();
                PveManager.Instance.Init(1);
            }
            else
            {
                PveManager.Instance.Init();
            }

        }

        public static void Init()
        {
#if UNITY_EDITOR
            PlayerSettings.runInBackground = true;
#endif
//#if UNITY_EDITOR

            if (pveRoot != null)
            {
                return;
            }

            pveRoot = new GameObject("[PVE]");
            pveRoot.AddComponent<PveTest>();
            pveRootTrans = pveRoot.transform;
            var showOnGui = LocalPrefs.GetInt("ShowPveOnGUI");
            if (showOnGui == 1)
            {
                PveScene.isShowPveTestOnGUI = true;
            }

            var preloadRpgScene = LocalPrefs.GetInt("PreloadRpgScene");
            if (preloadRpgScene == 1)
            {
                PveGlobalVlues.PreloadRpgScene = true;
            }

//#endif
        }

        public static void EnterPveBattle()
        {
            isInited = true;
            PveManager.Instance.EnterPveBattle();
        }

        public static void UpdateCardInfo(LuaTable table)
        {
            PveUtils.UpdateCardInfo(table);
        }


        public static void UpdatePveHeroes(LuaTable table)
        {
            PveUtils.UpdatePveHeroes(table);
        }

        public static void UpdatePveCards(LuaTable table)
        {
            PveUtils.UpdatePveCards(table);
        }

        public static void OnClickSkill(int id)
        {
            OperationManager.Instance.OnClickSkill(id);
        }

        public static void SkillTouchStart(int id, GameObject card)
        {
            OperationManager.Instance.SkillTouchStart(id, card);
        }

        public static void SkillTouchEnd(int id, GameObject card)
        {
            OperationManager.Instance.SkillTouchEnd(id, card);
        }

        public static void SkillDragStart(int id, Vector2 position)
        {
            OperationManager.Instance.SkillDragStart(id, position);
        }

        public static void SkillDragEnd(int id)
        {
            OperationManager.Instance.SkillDragEnd(id);
        }

        public static void SkillDragOutEnd(int id)
        {
            OperationManager.Instance.SkillDragOutEnd(id);
        }

        public static void SkillDrag(int id, Vector2 position)
        {
            OperationManager.Instance.SkillDrag(id, position);
        }

        public static void PlayCDAnimation(int index)
        {
            //PveManager.Instance.PlayCardCDAnim(index);
        }

        public static void ChangeSpeed(float speed)
        {
            PveManager.Instance.TimeSpeed = speed;
            //TimeManager.gameTimeScale = PveManager.Instance.TimeSpeed;
            Time.timeScale = PveManager.Instance.TimeSpeed;
        }

        public static void ChangeAuto(bool isAuto)
        {
            PveManager.Instance.IsAuto = isAuto;
            if (isAuto)
            {
                PveCardManager.Instance.RefreshAutoCastList();
            }
        }

        public static void OnClickHero(int id)
        {
            if (IsToTurnBase)
            {
                TurnBaseManager.Instance.UnitAttack(id);
            }
            else
            {
                OperationManager.Instance.OnClickHero(id);
            }
        }

        public static void OnSlideHero(int id)
        {
            if (IsToTurnBase)
            {
                TurnBaseManager.Instance.UnitSkill(id);
            }
        }

        public static void OnClickUltra()
        {
            if (IsToTurnBase)
            {
                TurnBaseManager.Instance.UltraSkill();
            }
        }


        public static void Exit()
        {
            isInited = false;
            PveManager.Instance.Dispose();
        }

        public static void BeginBlackFade(float startAlpha, float endAlpha, float fadeTime, LuaFunction function)
        {
            HCameraManager.BeginBlackFade(startAlpha, endAlpha, fadeTime, () => { function?.Call(); });
        }

        public static void PreloadRpgSummonConfig(LuaTable table)
        {
            PveUtils.PreloadRpgSummonConfig(table);
        }

        public static void PreloadRpgObstacleConfig(LuaTable table)
        {
            PveUtils.PreloadRpgObstacleConfig(table);
        }

        public static void PreloadRpgEffectConfig(LuaTable table)
        {
            PveUtils.PreloadRpgEffectConfig(table);
        }

        public static void PreloadRpgHeroConfig(LuaTable table)
        {
            PveUtils.PreloadRpgHeroConfig(table);
        }

        public static void PreloadRpgSkillConfig(LuaTable table)
        {
            PveUtils.PreloadRpgSkillConfig(table);
        }

        public static void PreloadRpgBulletConfig(LuaTable table)
        {
            PveUtils.PreloadRpgBulletConfig(table);
        }

        public static void PreloadRpgElementConfig(LuaTable table)
        {
            PveUtils.PreloadRpgElementConfig(table);
        }

        public static void PreloadRpgWeaponConfig(LuaTable table)
        {
            PveUtils.PreloadRpgWeaponConfig(table);
        }

        public static void PreloadRpgResourceConfig(LuaTable table)
        {
            PveUtils.PreloadRpgResourceConfig(table);
        }

        public static void PreloadRpgNpcEventConfig(LuaTable table)
        {
            PveUtils.PreloadRpgNpcEventConfig(table);
        }

        public static void PreloadRpgNpcDialogConfig(LuaTable table)
        {
            PveUtils.PreloadRpgNpcDialogConfig(table);
        }

        public static void PreloadRpgNpcDialogContentConfig(LuaTable table)
        {
            PveUtils.PreloadRpgNpcDialogContentConfig(table);
        }

        public static void PreloadRpgLevelMonsterConfig(LuaTable table)
        {
            PveUtils.PreloadRpgLevelMonsterConfig(table);
        }

        public static void PreloadRpgModelPlaceConfig(LuaTable table)
        {
            PveUtils.PreloadRpgModelPlaceConfig(table);
        }

        public static void PreloadRpgSpecialObjectConfig(LuaTable table)
        {
            PveUtils.PreloadRpgSpecialObjectConfig(table);
        }

        public static void SetRpgLevelId(int levelId, bool isInitialize = false)
        {
            LevelId = levelId;
            if (isInitialize)
            {
                PveManager.Instance.RpgLevelId = levelId;
            }
        }

        public static void PreloadRpgMonsterConfig(LuaTable table)
        {
            PveUtils.PreloadRpgMonsterConfig(table);
        }

        public static void PreloadRpgModelConfig(LuaTable table)
        {
            PveUtils.PreloadRpgModelConfig(table);
        }

        public static void PreloadExternalHeroConfig(LuaTable table)
        {
            PveUtils.PreloadExternalHeroConfig(table);
        }

        public static void UpdatePveHeroAttributes(LuaTable table)
        {
            PveUtils.UpdatePveHeroAttributes(table);
        }

        public static void UpdatePveMonsterAttributes(LuaTable table)
        {
            PveUtils.UpdatePveMonsterAttributes(table);
        }

        public static void UpdatePveMonsterLevels(LuaTable table)
        {
            PveUtils.UpdatePveMonsterLevels(table);
        }

        public static void SetIsTest(bool isTest)
        {
            PveGlobalVlues.IsTestBattle = isTest;
        }
        
        public static void StartPveScene()
        {
            PveManager.Instance.StartPveScene();
        }

        public static void ResumeAfk()
        {
            PveManager.Instance.ResumeAfk();
        }

        public static void SetCameraEnable()
        {
            PveManager.Instance.SetCameraEnable();
        }

        public static void PauseAfk()
        {
            PveManager.Instance.PauseAfk();
        }

        public static void LogicPause()
        {
            PveManager.Instance.LogicPause();
        }

        public static void LogicResume()
        {
            PveManager.Instance.LogicResume();
        }
        


        public static void PreloadLangConfigs(LuaTable table)
        {
            PveUtils.PreloadLangConfigs(table);
        }

        public static Vector3 GetPveCameraForward()
        {
            return -PveCameraManager.Instance.mainCamera.transform.forward;
        }

        public static Camera GetPveCamera()
        {
            return PveCameraManager.Instance.mainCamera;
        }

        public static void UpdateRpgCostValue(float init, float recovery)
        {
            PveGlobalVlues.InitTeamEnergy = init;
            PveGlobalVlues.TeamEnergyRecoverSpeed = recovery;
            PveGlobalVlues.EnemyEnergyRecoverSpeed = recovery;
        }

        public static void HideAllHeroes()
        {
            UnitManager.Instance.HideAllHeroes();
        }

        public static void UpdateRpgLevelTime(int time)
        {
            PveGlobalVlues.rpgLevelTime = time;
        }
        
        public static void SetCinemachineCameraStyleAndTime(CinemachineBrain brain, int style, float time)
        {
            brain.m_DefaultBlend.m_Style = (CinemachineBlendDefinition.Style) style;
            brain.m_DefaultBlend.m_Time = time;
        }

        public static void SetCinemachineCameraFov(CinemachineVirtualCamera camera, float fov)
        {
            camera.m_Lens.FieldOfView = fov;
        }

        public static void SetCinemachineCameraNearClipPlane(CinemachineVirtualCamera camera, float near)
        {
            camera.m_Lens.NearClipPlane = near;
        }

        public static void SetCinemachineCameraFarClipPlane(CinemachineVirtualCamera camera, float far)
        {
            camera.m_Lens.FarClipPlane = far;
        }


        /*public static void EnumerableToLuaTable<T>(object obj)
        {
            if (obj is IEnumerable<T> enumerable)
            {
                Debug.LogError("Success");
            }
        }*/

        public static string GetShaderTagZTestMode()
        {
            return ShaderUtilities.ShaderTag_ZTestMode;
        }

        public static void ResizeTextWithFixedWidthAndLine(RectTransform rectTransform, float fixedWidth, int line)
        {
            var text = rectTransform.GetComponent<YText>();
            if (text)
            {
                TextGenerator tg = text.cachedTextGeneratorForLayout;
                rectTransform.sizeDelta = new Vector2(fixedWidth, rectTransform.sizeDelta.y);
                var size = rectTransform.sizeDelta;
                TextGenerationSettings settings = text.GetGenerationSettings(size);
                var height = tg.GetPreferredHeight(text.text, settings);
                //Debug.LogError(height);
                var extraHeight = height - size.y;
                if (extraHeight > 0)
                {
                    var lines = Mathf.CeilToInt(extraHeight / (text.lineSpacing * 2 * text.fontSize));
                    var extraWidth = lines * rectTransform.sizeDelta.x / line;
                    rectTransform.sizeDelta = new Vector2(extraWidth + fixedWidth, size.y);
                }
                else
                {
                    rectTransform.sizeDelta = new Vector2(fixedWidth, size.y);
                }

                /*var singleLineWidth = height / 3;
                singleLineWidth = Mathf.Max(singleLineWidth, 313);
                rectTransform.sizeDelta = new Vector2(singleLineWidth,rectTransform.sizeDelta.y);*/
            }
        }

        //如果为单行，则宽度适应
        //如果为多行，则以参数的宽度进行高度适应
        public static void ResizeTextWidthMaxWidth(RectTransform rectTransform, float fixedWidth)
        {
            var text = rectTransform.GetComponent<YText>();
            if (text)
            {
                TextGenerator tg = text.cachedTextGeneratorForLayout;
                rectTransform.sizeDelta = new Vector2(fixedWidth, rectTransform.sizeDelta.y);
                var size = rectTransform.sizeDelta;
                TextGenerationSettings settings = text.GetGenerationSettings(size);
                var height = tg.GetPreferredHeight(text.text, settings);
                var width = tg.GetPreferredWidth(text.text, settings);
                if (width >= fixedWidth)
                {
                    rectTransform.sizeDelta = new Vector2(fixedWidth, height);
                }
                else
                {
                    rectTransform.sizeDelta = new Vector2(width, height);
                }
            }
        }


        public static void BornPositionCheck(string path,Vector3 position,Vector3 forward)
        {
#if UNITY_EDITOR
            var scene = AssetDatabase.LoadAssetAtPath<GameObject>(path);
            if (scene == null)
            {
                Debug.LogError(path+"为空");
                return;
            }
            var sceneData = scene.GetComponent<RpgBattleSceneData>();
            if (sceneData)
            {
                var battleQuaternion = Quaternion.FromToRotation(Quaternion.Euler(0, sceneData.rotation.y, 0) * Vector3.forward,
                    scene.transform.forward);
            }
#endif
            
        }
       
        public static void CheckAttachGround(Transform point,bool showLog = false)
        {
            var position = GetAttachGroundPoint(point.position,point.name);
            var diff = Mathf.Abs(point.position.y - position.y);
            if (showLog && diff >= 0.01f)
            {
                Debug.LogError(point.name + " 原始:"+ point.position + " 现在:" + position);
            }
            point.position = position;
            
        }
        
        public static Vector3 GetAttachGroundPoint(Vector3 position,string name = null)
        {
            var originPosition = position;
            position += new Vector3(0, 0.5f, 0);
            float closest = 9999;
            bool find = false;
            var rayCastAll = Physics.RaycastAll(position, Vector3.up, 5f);
            for (int i = 0; i < rayCastAll.Length; i++)
            {
                var hit = rayCastAll[i];
                var pointOnMesh = BunkerHitPoint.FindNearestPointOnMesh(position,hit.transform);
                var distance = Mathf.Abs(closest - position.y);
                var d = Mathf.Abs(pointOnMesh .y - position.y);
                if (d < distance)
                {
                    find = true;
                    closest = pointOnMesh.y;
                }
            }
            rayCastAll = Physics.RaycastAll(position, Vector3.down, 5f);
            for (int i = 0; i < rayCastAll.Length; i++)
            {
                var hit = rayCastAll[i];
                var pointOnMesh = BunkerHitPoint.FindNearestPointOnMesh(position,hit.transform);
                var distance = Mathf.Abs(closest - position.y);
                var d = Mathf.Abs(pointOnMesh .y - position.y);
                if (d < distance)
                {
                    find = true;
                    closest = pointOnMesh.y;
                }
            }

            if (!find)
            {
                closest = originPosition.y;
                if (name == null)
                {
                    name = originPosition.ToString();
                }
                Debug.LogError(name + " 找不到碰撞");
            }

            return new Vector3(position.x, closest, position.z);
        }
    }
}
